package net.nyx.printerservice.print;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;

import com.example.sunmiv1.entity.PrintInfoBean;
import com.example.sunmiv1.utils.LogUtil;
import com.example.sunmiv1.utils.MathUtil;
import com.example.sunmiv1.utils.net.ACache;

import org.xprinter.XprinterManager;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 海外 (兼容所有機型 ，NB55正版GMS A13除外)
 * https://github.com/SZNoryox/PrinterClient
 *
 * <p>
 * 具體實現通信通道類
 */
public class DeviceServiceChannel {


    private static final String REMOTE_SERVICE_PACKAGE_NAME = "net.nyx.printerservice";
    private static final String REMOTE_SERVICE_ACTION = "net.nyx.printerservice.IPrinterService";


    private IPrinterService remotePrinterService;
    private final ServiceConnection serviceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            remotePrinterService = IPrinterService.Stub.asInterface(service);
            // getVersion();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            remotePrinterService = null;
        }


    };

    private static final DeviceServiceChannel instance = new DeviceServiceChannel();

    public static DeviceServiceChannel getInstance() {
        return instance;
    }

    Context mContext;

    public void bindRemoteServiceTask(Context context) {
        if (context == null) {
            throw new NullPointerException("context is must not null");
        }
        Intent intent = new Intent();
        intent.setPackage(REMOTE_SERVICE_PACKAGE_NAME);
        intent.setAction(REMOTE_SERVICE_ACTION);
        mContext = context.getApplicationContext();
        mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    public void unbindRemoteServiceTask(Context context) {
        if (context == null) {
            throw new NullPointerException("context is must not null");
        }
        context.getApplicationContext().unbindService(serviceConnection);
    }

    public int getPrinterVersion() {
        if (remotePrinterService == null) {
            throw new NullPointerException("must be bindRemoteServiceTask");
        }
        try {
            return remotePrinterService.getPrinterVersion(new String[1]);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }

    public void triggerQscScan() {
        try {
            int res = remotePrinterService.triggerQscScan();
            if (res != SdkResult.SDK_OK) {
                PrintErrorMsg.msg(res);
                return;
            }
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }


    String blank="               ";

    private int printTextTask(String tag, PrintTextFormat format) {
        int res = SdkResult.SDK_UNKNOWN_ERR;
        try {
            // int res = remotePrinterService.printText(tag, format);
            /*   int res = remotePrinterService.printText2(tag, format,*//*58*4*//* 256, 1);
            if (res != SdkResult.SDK_OK) {
                PrintErrorMsg.msg(res);
                return;
            }*/

            /*if (format.getTextSize() != 24) {
                byte font = (byte) format.getTextSize();
                // 0x1b, 0x61 对其方式。0x01 剧中        0x1b, 0x21,  选择字体放大倍数  48
               remotePrinterService.printEscposData(new byte[]{0x1b, 0x61, 0x00, 0x1b, 0x21, font});// 0or48: Left,
            }else{
                remotePrinterService.printEscposData(new byte[]{0x1b, 0x61, 0x00, 0x1b, 0x21, 00});// 0or48: Left,
            }*/

            byte[] formater = new byte[]{0x1b, 0x61, 0x00, 0x1b, 0x21, 00};
            if (format.getTextSize() != 24) {
                //byte font = (byte) format.getTextSize();
                formater[5]=(byte) format.getTextSize();
            }
            remotePrinterService.printEscposData(formater);// 0or48: Left,

            //byte[] body= (blank+tag+"\n").getBytes("GBK");
            byte[] body= (blank+tag+"\n").getBytes(StandardCharsets.UTF_8);
        /*    byte[] body = (tag + "\n").getBytes(StandardCharsets.UTF_8);
            int iNum = 0;
            byte[] buff = new byte[body.length + 4];
            buff[0] = 0x1B;
            buff[1] = 0x24;
            buff[2] = (byte) (space % 256);
            buff[3] = (byte) (space / 256);
            System.arraycopy(body, 0, buff, 4, body.length);
            res = remotePrinterService.printEscposData(buff);*/

            res = remotePrinterService.printEscposData(body);
            if (res != SdkResult.SDK_OK) {
                PrintErrorMsg.msg(res);
                return res;
            }
            // 1or49: Center, 2or50: Rigth)
        } catch (Exception e) {
            LogUtil.e(e.toString());
        }
        return res;
    }

    int space=180;

    public byte[] buildTableText(String[] texts, int[] weights) {
        byte[] buf = new byte[100];
        byte[] tmp = null;
      /*  try {
            tmp = blank.getBytes("GBK");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }*/
        tmp = blank.getBytes(StandardCharsets.UTF_8);
        System.arraycopy(tmp, 0, buf, 0, tmp.length);
        int iNum = tmp.length;
        int max = 384;
        int len = weights.length;
        if (texts.length == weights.length) {

            int[] weightWidth = new int[len];
            for (int i = 0; i < len; i++) {
                weightWidth[i] = weights[i];
                if (i - 1 >= 0) {
                    weightWidth[i] = weights[i] + weightWidth[i - 1];
                }
            }
            for (int i = 0; i < len; i++) {
                /*try {
                    tmp = texts[i].getBytes("GBK");
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }*/
                tmp = texts[i].getBytes(StandardCharsets.UTF_8);
                System.arraycopy(tmp, 0, buf, iNum, tmp.length);
                iNum += tmp.length;
                if (i + 1 < len) {
                    // 第一个字段结束 x
                    // offset 内容长度
                    int offset = max / weightWidth[len - 1] * weightWidth[i] + 198;
              /*  if (formats[i + 1] == 1) {
                    offset = offset + (texts[i + 1].length() * 12) / 2;
                } else if (formats[i + 1] == 2) {
                    offset = offset + texts[i + 1].length() * 12;
                }*/

                    /*tmp = setPosition(offset);
                    System.arraycopy(tmp, 0, buf, iNum, tmp.length);
                    iNum += tmp.length;*/
                    buf[iNum] = 0x1B;
                    buf[1+iNum] = 0x24;
                    buf[2+iNum] = (byte) (offset % 256);
                    buf[3+iNum] = (byte) (offset / 256);
                    iNum += 4;
                }
            }
            buf[iNum] = '\n';

            return buf;
        }
        return buf;
    }


    //1B 24 设置横向绝对打印位置
    private byte[] setPosition(int offset) {
        byte[] bs = new byte[4];
        bs[0] = 0x1B;
        bs[1] = 0x24;
        bs[2] = (byte) (offset % 256);
        bs[3] = (byte) (offset / 256);
        return bs;
    }


    private int printProductTableModule(List<PrintInfoBean.DataBean.GoodsBean> goodsBeans) throws RemoteException {
        int res = 0;
        if (goodsBeans != null && !goodsBeans.isEmpty()) {
            int[] weights = {2, 1, 1, 1};
            String[] title = {"名稱", "數量", "單價", "金額"};
            byte[] data = buildTableText(title, weights);
            res = remotePrinterService.printEscposData(data);
            if (res != SdkResult.SDK_OK) {
                PrintErrorMsg.msg(res);
                return res;
            }
            for (int i = 0; i < goodsBeans.size(); i++) {
                PrintInfoBean.DataBean.GoodsBean goodsBean = goodsBeans.get(i);
                String goodsName = goodsBean.getGoods_name().trim();
                //String goodsName = "好市多巧克力超级黄金大礼包";
                if(goodsName.length()>7){
                    printTextTask(goodsName.substring(0,7),  new PrintTextFormat());
                    goodsName=goodsName.substring(7);
                }
                String[] column = new String[4];
                column[0] = goodsName;
                if ("2".equals(goodsBean.getPricing_method())) {
                    DecimalFormat df = new DecimalFormat("0");
                    column[1] = df.format(goodsBean.getNum()) + goodsBean.getCompany();
                } else {
                    DecimalFormat df = new DecimalFormat("0");
                    column[1] = df.format(goodsBean.getNum());
                }
                DecimalFormat df = new DecimalFormat("0"); // 只保留整数部分
                column[2] =  df.format(goodsBean.getPrice()); // 打印文字
                String allMoney=goodsBean.getAll_money();
                if(allMoney.endsWith(".00")){
                    allMoney=allMoney.substring(0,allMoney.length()-3);
                }
                column[3] =  allMoney;

                byte[] datas = buildTableText(column, weights);
                res = remotePrinterService.printEscposData(datas);
                String sku_name = goodsBean.getSku_name();
             /*   if ((sku_name == null || sku_name.isEmpty())&& i==0) {
                    sku_name = "好市多巧克力超级黄金大礼包,加珍珠，少冰，半糖，加巧克力";
                }*/
                if(sku_name!=null && !sku_name.isEmpty()){
                    sku_name=sku_name.trim();
                    if (sku_name.length() > 16) {
                        printTextTask(sku_name.substring(0, 16), new PrintTextFormat());
                        sku_name = sku_name.substring(16);
                    }
                    printTextTask(sku_name,  new PrintTextFormat());
                }


                if (res != SdkResult.SDK_OK) {
                    PrintErrorMsg.msg(res);
                    return res;
                }
            }


        }

        return res;
    }

    /**
     *
     */
    public void printPayReceipt(PrintInfoBean printInfoBean, String billNumber, String date, String time,String remake,double money,double changeMoney) {
        //【ESC @】 初始化打印机 1B  40
        try {
            int res = remotePrinterService.printEscposData(new byte[]{0x1b, 0x40});
            if (res != SdkResult.SDK_OK) {
                PrintErrorMsg.msg(res);
                return;
            }
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
        PrintTextFormat format0 = new PrintTextFormat();
        //format0.setTextSize(26);
        printTextTask(printInfoBean.getData().getStore_name() + "小店\n", format0);
        PrintTextFormat format = new PrintTextFormat();
        printTextTask("收銀小票", format);

        //printTextTask("訂單詳情\n", format);
        String orderType = printInfoBean.getData().getOrder_type();
        if (orderType == null || orderType.isEmpty()) {
            orderType = "店內訂單";
        }
        printTextTask("訂單類型:" + orderType, format);
        if (billNumber == null || billNumber.isEmpty()) {
            billNumber = printInfoBean.getData().getOrder_no();
        }

        printTextTask("訂單編號:" + billNumber, format);
        //
        String dateTime;
        if (!date.isEmpty() && !time.isEmpty()) {
            try {
                SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMddHHmmss");
                Date data = originalFormat.parse(date + time);
                dateTime = new SimpleDateFormat("yyyy-MM-dd").format(data);
            } catch (Exception e) {
                dateTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            }
        } else {
            dateTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        }
        printTextTask("訂單時間:" + dateTime, format);

        String billNo = "";
        Integer no = printInfoBean.getData().getPrint_number();
        if (no != null) {
            billNo = buildBillNo(no.toString());
        }
        if (billNo.isEmpty()) {
            String order_no = printInfoBean.getData().getOrder_no();
            billNo = order_no.substring(order_no.length() - 4, order_no.length());
        }
        printTextTask("編號:" + billNo, format);

        printTextTask("*******************************",  new PrintTextFormat());
        try {
            int res = printProductTableModule(printInfoBean.getData().getGoods());
            if (res != SdkResult.SDK_OK) {
                PrintErrorMsg.msg(res);
                return;
            }
        } catch (RemoteException e) {
            LogUtil.e("TAG", " printPayReceipt  RemoteException --------------> " + e.toString());
        }
        printTextTask("*******************************",  new PrintTextFormat());
        // "finish_time":"2019/06/24 18:54:50"
        String paTime;
        try {
            paTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        } catch (Exception e) {
            paTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        }
        printTextTask("支付時間：" + paTime, format);
        printTextTask("訂單號:" + billNumber, format);

        //printTextTask("應收金額：" + String.format("%.2f", printInfoBean.getData().getAll_money()), format);
        DecimalFormat df = new DecimalFormat("0");
        printTextTask("應收金額：" + df.format(printInfoBean.getData().getAll_money()), new PrintTextFormat());
        DecimalFormat df1 = new DecimalFormat("0");
        if(money>=0){
            printTextTask("實際金額：" + df.format(money), format);
        }else {
            printTextTask("實際金額：" + df.format(printInfoBean.getData().getAmount_received()), format);
        }

        List<PrintInfoBean.DataBean.PayListBean> payList = printInfoBean.getData().getPayList();
        for (int i = 0; i < payList.size(); i++) {
            StringBuilder pay = new StringBuilder();
            if (!date.isEmpty() && !time.isEmpty()) {
                String payType = "支付方式：在綫支付";
                pay.append(payType);
            } else {
                String payType = "支付方式：" + payList.get(i).getName();
                pay.append(payType);
            }
            printTextTask(pay.toString(), format);
        }
        //printTextTask("優惠金額：" + String.format("%.2f", printInfoBean.getData().getCoupon_money()), format);
        DecimalFormat df2 = new DecimalFormat("0");
        printTextTask("優惠金額：" +  df2.format(printInfoBean.getData().getCoupon_money()), format);

        double back = printInfoBean.getData().getAmount_received() - printInfoBean.getData().getAll_money() - printInfoBean.getData().getCoupon_money();
        back = back >= 0 ? back : 0.0;
        if(money>=0){
            DecimalFormat df3 = new DecimalFormat("0");
            printTextTask("找零金額：" + df3.format(changeMoney), format);
        }else {
            DecimalFormat df3 = new DecimalFormat("0");
            printTextTask("找零金額：" + df3.format( back), format);
        }
        if(!remake.isEmpty()){
            printTextTask("訂單備註:" + remake, format);
        }
        PrintTextFormat format1 = new PrintTextFormat();
        printTextTask("加入官方line", format1);

        try {
            //int res = remotePrinterService.paperOut(160);
            int res= remotePrinterService.printEscposData(new byte[]{0x1d, 0x56, 0x42, 0x0A});
            //int res = remotePrinterService.printEscposData(nextLines2(16));
            if (res != SdkResult.SDK_OK) {
                PrintErrorMsg.msg(res);
                return;
            }
        } catch (RemoteException e) {
            LogUtil.e("TAG", " printPayReceipt  RemoteException ---> " + e.toString());
            throw new RuntimeException(e);
        }

    }

    public static byte[] nextLines2(int lineNum) {
        byte[] result = new byte[3];
        result[0] = 0x1B;// 0x1B ESC
        result[1] = 0x64;// 0x64;
        result[2] = (byte) lineNum;
        return result;
    }


    String buildBillNo(String no) {
        if (no.length() < 4) {
            return buildBillNo("0".concat(no));
        } else {
            return no;
        }
    }
    void printBillNumLabelBarCode(String billNumber, String date) {
        try {
            PrintTextFormat format = new PrintTextFormat();
            //remotePrinterService.printText("\nModel:\t\tNB55", format);
            remotePrinterService.printBarcode(billNumber, 500, 160, 2, 1);
            //remotePrinterService.printText("Time:" + date, format);

            /*remotePrinterService.printText("\n\n", new PrintTextFormat());
            int ret = remotePrinterService.labelLocate(240, 16);
            if (ret == 0) {
                PrintTextFormat format = new PrintTextFormat();
                //remotePrinterService.printText("\nModel:\t\tNB55", format);
                remotePrinterService.printBarcode(billNumber, 360, 90, 0, 1);
                remotePrinterService.printText("Time:" + date, format);
                ret = remotePrinterService.labelPrintEnd();
            }*/
        } catch (Exception e) {
            // throw  Exception(e);
        }

    }

}
